package view;

import java.net.URL;
import java.util.Vector;
import java.util.Observable;
import java.util.Observer;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

import model.CategoryDataModel;

import riverlayout.component.*;
import controller.CategoryController;

/**
 * 12-01-2010
 * 
 * This class is the view for making and editing categories.
 * 
 * @author Martijn Scholten & Michel Rondhuis        
 */
public class CategoryView extends JPanel implements Observer {

	private static JFrame frame;
	private static final long serialVersionUID = 01;

	// Reference is the singleton reference
	private static CategoryView reference;

	// one panel with 2 JLabel 1 TextField and 2 buttons
	private JPanel generalFieldsPanel = new JPanel();

	private JLabel titleLabel = new JLabel("Titel");
	private JLabel errorLabel = new JLabel("");

	private JTextField titleTextField = new JTextField();

	private JButton cancelButton = new JButton("Annuleren");
	private JButton actionButton = new JButton();
	private JButton deleteButton = new JButton("Delete");

	private JComboBox categoryComboBox;

	private CategoryController controller;

	URL urlIcon = null;
	
	private int categoryId;

	/**
	 * This method must be called to (start and) get the instance.
	 */
	public static synchronized CategoryView getCategoryView(CategoryController controller) {
		if (reference == null) {
			reference = new CategoryView(controller);
		}
		return reference;
	}
	/**
	 * Needs the controller to initialize
	 * Initiates the CategoryView.
	 * 
	 * @param newController
	 */
	private CategoryView(CategoryController newController) {

		try {

			urlIcon = getClass().getClassLoader().getResource("pics/icon.jpg");

		} catch(NullPointerException x) {
			x.printStackTrace();
			throw x;
		}
		
		controller = newController;

		// Setup of the frame
		frame = new JFrame();
		frame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
		frame.setSize(350, 140);
		frame.setContentPane(this);
		frame.requestFocus();
		frame.setTitle("Categorie Beheer");
		frame.setResizable(false);
		frame.setIconImage(new ImageIcon(urlIcon).getImage());
		// Setup of elements
		titleTextField.setSize(100, 20);
		// actionButton.addActionListener(controller);
		cancelButton.addActionListener(new CancelButtonHandler());
		actionButton.addActionListener(controller);
		deleteButton.addActionListener(new DeleteButtonHandler());
		deleteButton.setEnabled(false);

		categoryComboBox =  new JComboBox();
		categoryComboBox.addItem("Nieuwe Categorie");
		fillCategoryComboBox();
		
		titleTextField.setDocument(new MaxCharHandler(30));
		
		categoryComboBox.addActionListener(new ComboBoxHandler());

		//Borders for the elements
		titleTextField.setBorder(BorderFactory.createLineBorder(Color.black));
		categoryComboBox.setBorder(BorderFactory.createLineBorder(Color.black));

		// Adding all the elements starts here
		setLayout(new BorderLayout());

		add(generalFieldsPanel, BorderLayout.WEST);

		generalFieldsPanel.setLayout(new RiverLayout());

		generalFieldsPanel.add("left", new JLabel("Categorie"));
		generalFieldsPanel.add("hfill", categoryComboBox);
		generalFieldsPanel.add("br", titleLabel);
		generalFieldsPanel.add("tab hfill", titleTextField);
		generalFieldsPanel.add("br, hfill", errorLabel);
		generalFieldsPanel.add("br", actionButton);
		generalFieldsPanel.add(deleteButton);
		generalFieldsPanel.add(cancelButton);
	}
	
	/**
	 * Fills the categoryComboBox with data
	 * It get its data from the controller.
	 */
	private void fillCategoryComboBox() {
		int itemCount = categoryComboBox.getItemCount();
		for(int i = itemCount - 1; i > 0; i--) {
			categoryComboBox.removeItemAt(i);
		}
		Vector<CategoryDataModel> categoryList = controller.getCategoryList();
		for(CategoryDataModel c : categoryList) {
			categoryComboBox.addItem(c);
		}
	}

	/**
	 * This method is called whenever the observed object is changed.
	 * 
	 * @param observable
	 * @param argument
	 */
	public void update(Observable observable, Object argument) {
		hide();
	}
	
	/*
	 * (non-Javadoc)
	 * @see java.awt.Component#hide()
	 */
	@Override
	public void hide() {
		frame.setVisible(false);
	}

	/**
	 * Uses an Boolean to determine if there is an new category or an existing category.
	 */
	public void showNewOrEditCategoryOnBool(boolean newCategory) {
		fillCategoryComboBox();
		if (newCategory) {
			actionButton.setText("Opslaan");
		} else {
			actionButton.setText("Wijzigen");
		}
		updateUI();
		frame.setVisible(true);
	}

	// Setter methods start here
	/**
	 * Sets the titleTextField's contents
	 * Change the title textfield contents.
	 * 
	 * @param inputText         
	 */
	public void setTitleField(String inputText) {
		titleTextField.setText(inputText);
	}

	/**
	 * Sets the CategoryId.
	 * 
	 * @param newCategoryId
	 */
	public void setCategoryId(int newCategoryId) {
		categoryId = newCategoryId;
	}

	// Getter methods start here
	/**
	 * Returns the current text in the titletextfield.
	 * 
	 * @return the current text in titleTextField
	 */
	public String getTitle() {
		return titleTextField.getText();
	}

	/**
	 * @return the Id for editing purposes
	 */
	public int getIdCategory() {
		return categoryId;
	}
	/**
	 * Gets the title of categoryComboBox.
	 * @return The selected title of combobox
	 */
	public String getComboTitle() {
		return (String) categoryComboBox.getSelectedItem();
	}
	/**
	 * Gets the input category on the view.
	 * 
	 * @return categoryComboBox selectedItem
	 */
	public CategoryDataModel getInputCategory() {
		if(categoryComboBox.getSelectedItem() instanceof CategoryDataModel) {
			return (CategoryDataModel) categoryComboBox.getSelectedItem();
		} else {
			return null;
		}
	}

	/**
	 * This class is the actionlistener for the cancel button.
	 */
	class CancelButtonHandler implements ActionListener {
		/**
		 * Hides the window
		 */
		public void actionPerformed(ActionEvent arg0) {
			hide();
		}
	}

	/**
	 * This class is the actionlistener for the deletebutton.
	 */
	class DeleteButtonHandler implements ActionListener {
		public void actionPerformed(ActionEvent arg0) {
			controller.deleteCategory(categoryId);
		}
	}

	/**
	 * This class is the actionlistener to get the text from the
	 * Jcombobox to the titletextfield.
	 *
	 * @author Michel Rondhuis & Martijn Scholten 
	 */
	class ComboBoxHandler implements ActionListener {
		public void actionPerformed(ActionEvent arg0) {  
			String st = ((JComboBox) arg0.getSource()).getSelectedItem().toString();
			if(st == "Nieuwe Categorie") {
				titleTextField.setText("");

				deleteButton.setEnabled(false);
				actionButton.setText("Opslaan");
			} else {
				CategoryDataModel category = (CategoryDataModel) ((JComboBox) arg0.getSource()).getSelectedItem();
				categoryId = category.getId();
				titleTextField.setText(category.getTitle());
				deleteButton.setEnabled(true);
				actionButton.setText("Wijzigen");				
			}
		}
	}
	
	/**
	 * This class defines the maximum characters for JTextFields.
	 */
	private class MaxCharHandler extends PlainDocument {
		private static final long serialVersionUID = 1L;
		private int max = 10;
		
		public MaxCharHandler(int newMax) {
			max = newMax;
		} 
		
		/**
		 * This method inserts the string
		 */
		public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
			if (getLength()+str.length()>max) {
				str = str.substring(0, max - getLength());
			}
			super.insertString(offs, str, a);
		}
	}
}